<template>
  <div>
<!--  ==================流程定义列表===============  -->
    <a-card v-if="!xmlFrame.open||xmlView">
      <el-form :model="queryParams" ref="queryForm" :inline="true" v-show="showSearch" label-width="68px">
        <el-form-item label="流程名称" prop="name">
          <el-input
            v-model="queryParams.name"
            placeholder="请输入名称"
            clearable
            size="small"
            @keyup.enter.native="handleQuery"
          />
        </el-form-item>
        <el-form-item label="流程分类" prop="category">
          <el-select @change="handleQuery" v-model="queryParams.category" placeholder="请选择流程分类" clearable prop="category">
            <el-option label="请选择" value="" />
            <el-option v-for="category in categorys" :key="category.id" :label="category.name" :value="category.id" />
          </el-select>
        </el-form-item>
        <el-form-item label="激活" prop="active">
          <el-switch
            v-model="queryParams.active"
            active-color="#13ce66"
            inactive-color="#ff4949"
            @change="handleQuery"
          >
          </el-switch>
        </el-form-item>
        <el-form-item>
          <el-button type="primary" icon="el-icon-search" size="mini" @click="handleQuery">搜索</el-button>
          <el-button icon="el-icon-refresh" size="mini" @click="resetQuery">重置</el-button>
        </el-form-item>
        <!--<el-form-item style="float:right">
          <el-button
            type="primary"
            icon="el-icon-plus"
            size="mini"
            @click="handleLoadXml"
          >新增流程定义</el-button>
        </el-form-item>-->
      </el-form>
      <el-row :gutter="10" class="table-operator mb8">
        <el-col :span="1.5">
          <el-button
            type="primary"
            plain
            icon="el-icon-upload"
            size="mini"
            @click="handleImport"
          >导入</el-button>
        </el-col>
        <el-col :span="1.5">
          <el-button
            type="success"
            plain
            icon="el-icon-plus"
            size="mini"
            @click="handleLoadXml"
          >新增</el-button>
        </el-col>
        <right-toolbar :showSearch.sync="showSearch" @queryTable="handleQuery"></right-toolbar>
      </el-row>

      <el-table
        v-loading="loading" fit
        :data="definitionList"
        row-key="id"
        border
        lazy
        :load="load"
        @selection-change="handleSelectionChange"
        ref="flowTable"
        :tree-props="{children: 'children', hasChildren: 'hasChildren'}">
        <!--<el-table-column type="selection" width="55" align="center" />-->
        <el-table-column label="流程定义id" align="center" prop="id" />
        <el-table-column label="流程标识Key" align="center" prop="key"  />
        <el-table-column label="流程分类" align="center" >
          <template slot-scope="scope">
            <span>{{ getCategoryName(scope.row.category) }}</span>
          </template>
        </el-table-column>
        <el-table-column label="流程名称" align="center" :show-overflow-tooltip="true">
          <template slot-scope="scope">
            <el-button type="text" @click="handleReadImage(scope.row.deploymentId)">
              <span>{{ scope.row.name }}</span>
            </el-button>
          </template>
        </el-table-column>
        <el-table-column label="业务表单" align="center" :show-overflow-tooltip="true">
          <template slot-scope="scope">
            <el-button v-if="scope.row.formId" type="text" @click="handleForm(scope.row.formId)">
              <span>{{ scope.row.formName }}</span>
            </el-button>
            <label v-else>暂无表单</label>
          </template>
        </el-table-column>
        <el-table-column label="流程版本" align="center">
          <template slot-scope="scope">
            <el-tag size="medium" >v{{ scope.row.version }}</el-tag>
          </template>
        </el-table-column>
        <el-table-column label="状态" align="center">
          <template slot-scope="scope">
            <el-tag type="success" v-if="scope.row.suspensionState === 1">激活</el-tag>
            <el-tag type="warning" v-if="scope.row.suspensionState === 2">挂起</el-tag>
          </template>
        </el-table-column>
        <el-table-column label="部署时间" align="center" prop="deploymentTime" width="180"/>
        <el-table-column label="操作" align="center" class-name="small-padding fixed-width">
          <template slot-scope="scope">
            <el-dropdown>
            <span class="el-dropdown-link">
              更多操作<i class="el-icon-arrow-down el-icon--right"></i>
            </span>
              <el-dropdown-menu slot="dropdown">
                <el-dropdown-item icon="el-icon-edit-outline" @click.native="handleLoadXml(scope.row)">
                  编辑
                </el-dropdown-item>
                <el-dropdown-item icon="el-icon-connection" @click.native="handleAddForm(scope.row)" v-if="scope.row.formId == null">
                  配置表单
                </el-dropdown-item>
                <el-dropdown-item icon="el-icon-connection" @click.native="handleAddForm(scope.row)" v-if="scope.row.formId != null">
                  更改表单
                </el-dropdown-item>
                <el-dropdown-item icon="el-icon-video-pause" @click.native="handleUpdateSuspensionState(scope.row)" v-if="scope.row.suspensionState === 1">
                  挂起
                </el-dropdown-item>
                <el-dropdown-item icon="el-icon-video-play" @click.native="handleUpdateSuspensionState(scope.row)" v-if="scope.row.suspensionState === 2">
                  激活
                </el-dropdown-item>
                <el-dropdown-item icon="el-icon-delete" @click.native="handleDelete(scope.row)" >
                  删除
                </el-dropdown-item>
              </el-dropdown-menu>
            </el-dropdown>
          </template>
        </el-table-column>
      </el-table>
      <el-pagination
        v-show="total>0"
        :total="total"
        :current-page.sync="queryParams.pageNum"
        :page-size.sync="queryParams.pageSize"
        @size-change="getList"
        @current-change="getList"
      />
    </a-card>
    <!-- 流程图 -->
    <a-card v-if="xmlFrame.open&&!xmlView">
      <!--<a slot="extra" href="#" @click="()=>{xmlFrame.open=false}">返回</a>-->
      <bpmn-modeler
        v-if="xmlShow"
        ref="refNode"
        :xml="xmlData"
        :users="users"
        :groups="groups"
        :categorys="categorys"
        :is-view="xmlView"
        @save="save"
        @close="handleClose"
        @showXML="showXML"
        @dataType="dataType"
      />
      <!--在线查看xml-->
      <el-dialog :title="xmlTitle" :visible.sync="xmlOpen" width="60%" append-to-body>
        <div>
        <pre>
           <code class="xml">
                {{xmlContent}}
           </code>
        </pre>
        </div>
      </el-dialog>
    </a-card>
    <!--  弹窗预览  -->
    <flow :xmlData="xmlData" :open="xmlView&&xmlFrame.open" @closeChildDialog="()=>{xmlView=false,xmlFrame.open=false}"/>
    <!-- bpmn20.xml导入对话框 -->
    <el-dialog :title="upload.title" :visible.sync="upload.open" width="400px" append-to-body>
      <el-upload
        ref="upload"
        :limit="1"
        accept=".xml"
        :headers="upload.headers"
        :action="upload.url + '?name=' + upload.name+'&category='+ upload.category"
        :disabled="upload.isUploading"
        :on-progress="handleFileUploadProgress"
        :on-success="handleFileSuccess"
        :auto-upload="false"
        drag
      >
        <i class="el-icon-upload"></i>
        <div class="el-upload__text">
          将文件拖到此处，或
          <em>点击上传</em>
        </div>
        <div class="el-upload__tip" slot="tip">
          流程名称：<el-input v-model="upload.name"/>
          流程分类：<el-input v-model="upload.category"/>
        </div>
        <div class="el-upload__tip" style="color:red" slot="tip">提示：仅允许导入“bpmn20.xml”格式文件！</div>
      </el-upload>
      <div slot="footer" class="dialog-footer">
        <el-button type="primary" @click="submitFileForm">确 定</el-button>
        <el-button @click="upload.open = false">取 消</el-button>
      </div>
    </el-dialog>

    <!--表单配置详情-->
    <el-dialog :title="formView.title" :visible.sync="formView.open" width="50%" append-to-body>
      <div class="test-form">
        <parser :key="new Date().getTime()"  :form-conf="formConf" />
      </div>
    </el-dialog>

    <!--挂载表单-->
    <el-dialog :title="formDeploy.title" :visible.sync="formDeploy.open" width="70%" append-to-body>
      <el-form :model="formQueryParams" ref="queryDeployForm" :inline="true" label-width="68px">
        <el-form-item label="表单名称" prop="formName">
          <el-input
            v-model="formQueryParams.formName"
            placeholder="请输入表单名称"
            clearable
            size="small"
            @keyup.enter.native="handleQuery"
          />
        </el-form-item>
        <el-form-item>
          <el-button type="primary" icon="el-icon-search" size="mini" @click="handleFormQuery">搜索</el-button>
          <el-button icon="el-icon-refresh" size="mini" @click="resetFormQuery">重置</el-button>
        </el-form-item>
      </el-form>
      <el-row :gutter="24">
        <el-col :span="10" :xs="24">
          <el-table
            ref="singleTable"
            :data="formList"
            border
            highlight-current-row
            @current-change="handleCurrentChange"
            style="width: 100%">
            <el-table-column label="表单编号" align="center" prop="formId" />
            <el-table-column label="表单名称" align="center" prop="formName" />
            <el-table-column label="操作" align="center" class-name="small-padding fixed-width">
              <template slot-scope="scope">
                <el-button size="mini" type="text" @click="submitFormDeploy(scope.row)">绑定</el-button>
              </template>
            </el-table-column>
          </el-table>
          <el-pagination
            v-show="formTotal>0"
            :total="formTotal"
            :current-page.sync="formQueryParams.pageNum"
            :page-size.sync="formQueryParams.pageSize"
            @size-change="ListFormDeploy"
            @current-change="ListFormDeploy"
          />
        </el-col>
        <el-col :span="14" :xs="24">
          <div v-if="currentRow">
            <parser :key="new Date().getTime()" :form-conf="currentRow" />
          </div>
        </el-col>
      </el-row>
    </el-dialog>
  </div>
</template>

<script>
// import bpmnModeler from "workflow-bpmn-modeler";
import bpmnModeler from "@whflow/components/Process/index";
//import BpmnViewer from "bpmn-js/lib/Viewer";
import Flow from '@whflow/views/task/record/flow'

import {
  delDeployment,
  listDefinition,
  readXml,
  roleList,
  saveXml,
  updateState,
  userList
} from "@whflow/api/definition";
import { getToken } from "@/utils/auth";
import { getDicts } from '@/api/api'
import { getForm, addDeployForm ,listForm } from "@whflow/api/form";
import Parser from '@whflow/components/parser/Parser'
import vkbeautify from 'vkbeautify'
import Hljs from 'highlight.js'
import 'highlight.js/styles/atom-one-dark.css'

export default {
  components: {
    bpmnModeler,
    Parser,
    vkbeautify,
    Flow
  },
  // 自定义指令
  /*directives: {
    highlight:(el) => {
      let blocks = el.querySelectorAll('pre code');
      blocks.forEach((block) => {
        Hljs.highlightBlock(block)
      })
    }
  },*/
  data() {
    return {
      /*===================设计器属性======================*/
      users: [],
      groups: [],
      categorys: [],
      /*=================页面属性===================*/
      loading: true,
      // 选中数组
      ids: [],
      // 非单个禁用
      single: true,
      // 非多个禁用
      multiple: true,
      // 显示搜索条件
      showSearch: true,
      // 总条数
      total: 0,
      // 流程定义表格数据
      definitionList: [],
      allDefinitionList: [],
      // 查询参数
      queryParams: {
        pageNum: 1,
        pageSize: 10,
        name: null,
        category: null,
        key: null,
        tenantId: null,
        deployTime: null,
        derivedFrom: null,
        derivedFromRoot: null,
        parentDeploymentId: null,
        engineVersion: null
      },
      xmlFrame:{
        width:'70%',
        title:'流程图',
        open: false,
        src: "",
      },
      // xml
      xmlData:"",
      xmlShow: true,
      xmlView: false,
      // bpmn.xml 导入
      upload: {
        // 是否显示弹出层（xml导入）
        open: false,
        // 弹出层标题（xml导入）
        title: "",
        // 是否禁用上传
        isUploading: false,
        name: null,
        category: null,
        // 设置上传的请求头部
        headers: { Authorization: "Bearer " + getToken() },
        // 上传的地址
        url: process.env.VUE_APP_BASE_API + "/flowable/definition/import"
      },
      maps: new Map(),
      bpmnViewer: null,
      scale: 1,
      minScale: 1,

      // 挂载表单到流程实例
      formList: [],
      formTotal: 0,
      formConf: {}, // 默认表单数据
      formView:{
        title:'表单详情',
        open: false,
      },
      formDeploy:{
        title:'挂载表单',
        open: false,
      },
      formQueryParams:{
        formName: null,
        pageNum: 1,
        pageSize: 10,
      },
      formDeployParam:{
        formId: null,
        deployId: null
      },
      currentRow: null,
      // 在线查看xml
      xmlOpen: false,
      xmlTitle: '',
      xmlContent: '',
    };
  },
  created() {
    getDicts("sys_process_category").then((res) => {
      this.categorys = res;
    });
    this.initUserAndRole();
    this.getList();
  },
  methods: {
    /** 指定流程办理人员列表 */
    initUserAndRole(){
      userList({}).then(res=>{
        this.users = res.result||[]
        this.users.map(o=>{
          o.id = o.username
          o.name = o.realname
        })
        let arr = {name: "流程发起人", id: "${INITIATOR}"}
        this.users.push(arr)
      })
      roleList({}).then(res=>{
        this.groups = res.result||[]
        this.groups.map(o=>{
          o.name = o.roleName
        })
      })
    },

    /** xml 文件 */
    getModelDetail(deployId) {
      // 发送请求，获取xml
      readXml(deployId).then(res =>{
        this.xmlData = res.result;
      })
    },

    /** 流程分类翻译 */
    getCategoryName(category){
      let find = this.categorys.find(o=>o.id==category);
      if (find){
        return find.name
      }
      return ''
    },
    /*保存流程定义*/
    save(data) {
      //console.log(data);  // { process: {...}, xml: '...', svg: '...' }
      const params = {
        name: data.process.name,
        category: data.process.category,
        xml: data.xml
      }
      saveXml(params).then(res => {
        this.$message.success(res.message)
        // 关闭当前标签页并返回上个页面
        this.getList()
        this.xmlFrame.open = false
      })
    },
    /*================页面===============*/
    handleQuery() {
      this.queryParams.pageNum = 1;
      this.queryParams.suspensionState = this.queryParams.active?1:0;
      this.getList();
    },
    /** 查询流程定义列表 */
    getList() {
      return new Promise((resolve, reject) => {
        this.loading = true;
        // 最新版本
        const param1 = Object.assign({
          isLastVersion:1,
        },this.queryParams)
        listDefinition(param1).then(response => {
          this.definitionList = response.result.records;
          this.total = response.result.total;
          this.loading = false;
          for (const definition of this.definitionList) {
            definition.hasChildren = true
          }
        });
        // 所有
        const param2 = Object.assign({
          isLastVersion:0
        },this.queryParams,{
          pageSize: 9999,
          pageNum:1
        })
        listDefinition(param2).then(response => {
          this.allDefinitionList = response.result.records;
          resolve("加载完成")
        });
      });
    },
    /** 重置按钮操作 */
    resetQuery() {
      this.resetForm("queryForm");
      this.handleQuery();
    },
    resetForm(formName) {
      this.$refs[formName].resetFields()
    },
    // 多选框选中数据
    handleSelectionChange(selection) {
      this.ids = selection.map(item => item.id)
      this.single = selection.length!==1
      this.multiple = !selection.length
    },
    /** 打开流程设计弹窗页面 */
    handleLoadXml(row){
      if (row&&row.deploymentId){
        console.log(row.deploymentId)
        this.handleReadImage(row.deploymentId)
        this.xmlView = false
        this.xmlFrame.title = "编辑流程图";
      } else {
        //新增
        this.xmlData = ''
        this.xmlView = false
        this.xmlFrame.open = true
        this.xmlFrame.title = '新增流程'
        this.xmlShow = false
        this.$nextTick(()=>{
          this.xmlShow = true
        })
      }
      this.xmlFrame.width = '90%'
    },
    /** 流程图查看 */
    handleReadImage(deploymentId){
      this.xmlFrame.title = "流程图";
      this.xmlFrame.open = true;
      this.xmlFrame.width = '70%';
      // this.xmlFrame.src = process.env.VUE_APP_BASE_API + "/flowable/definition/xmlFrame/" + deploymentId;
      // 发送请求，获取xml
      this.xmlView = true
      readXml(deploymentId).then(res =>{
        if (res.success){
          this.xmlData = res.result
        } else {
          this.$message.error("获取流程图失败！")
        }
      })
    },
    /** 挂起/激活流程 */
    handleUpdateSuspensionState(row){
      let state = 1;
      if (row.suspensionState === 1) {
        state = 2
      }
      const params = {
        deployId: row.deploymentId,
        state: state
      }
      updateState(params).then(res => {
        this.$message.success(res.message);
        this.getList().then(val => {
          const { pid } = row;
          const { tree, treeNode, resolve } = this.maps.get(pid);
          this.$set(this.$refs.flowTable.store.states.lazyTreeNodeMap, pid, []);
          this.load(tree, treeNode, resolve);
        });
      });
    },
    /** 删除按钮操作 */
    handleDelete(row) {
      // const ids = row.deploymentId || this.ids;
      const params = {
        deployId: row.deploymentId
      }
      this.$confirm({
        title:"警告",
        content:'是否确认删除流程定义编号为"' + params.deployId + '"的数据项?',
        confirmButtonText: "确定",
        cancelButtonText: "取消",
        type: "warning",
        onOk:()=>{
          delDeployment(params).then(res=>{
            this.getList().then(val => {
              const { pid } = row;
              const { tree, treeNode, resolve } = this.maps.get(pid);
              this.$set(this.$refs.flowTable.store.states.lazyTreeNodeMap, pid, []);
              this.load(tree, treeNode, resolve);
            });
            if (res.success){
              this.$message.success('删除成功');
            } else {
              this.$message.success('删除失败');
            }
          })
        }
      })
    },
    /** 导入bpmn.xml文件 */
    handleImport(){
      this.upload.title = "bpmn20.xml文件导入";
      this.upload.open = true;
    },
    // 文件上传中处理
    handleFileUploadProgress(event, file, fileList) {
      this.upload.isUploading = true;
    },
    // 文件上传成功处理
    handleFileSuccess(response, file, fileList) {
      this.upload.open = false;
      this.upload.isUploading = false;
      this.$refs.upload.clearFiles();
      this.$message(response.msg);
      this.getList();
    },
    // 提交上传文件
    submitFileForm() {
      this.$refs.upload.submit();
    },
    // 加载子数据
    load(tree, treeNode, resolve) {
      const key = tree.key;
      const childrens = [];
      const pid = tree.id;
      this.maps.set(pid, {tree, treeNode, resolve});
      //console.log(this.maps.get(pid));
      for (const one of this.allDefinitionList) {
        if (one.key==key&&one.id!=tree.id){
          one.pid = pid;
          childrens.push(one)
        }
      }
      //console.log(tree, treeNode,this.allDefinitionList,childrens)
      resolve(childrens)
    },
    /** 表单搜索按钮操作 */
    handleFormQuery() {
      this.formQueryParams.pageNum = 1;
      this.ListFormDeploy()
    },
    /** 表单重置按钮操作 */
    resetFormQuery() {
      this.resetForm("queryDeployForm");
      this.handleFormQuery();
    },
    /** 表单查看 */
    handleForm(formId){
      getForm(formId).then(res =>{
        console.log(res)
        this.formView.title = "表单详情";
        this.formView.open = true;
        this.formConf = JSON.parse(res.result.formContent)
      })
    },
    /** 挂载表单弹框 */
    handleAddForm(row){
      this.formDeployParam.deployId = row.deploymentId
      this.ListFormDeploy()
    },
    /** 挂载表单列表 */
    ListFormDeploy(){
      listForm(this.formQueryParams).then(res =>{
        let result = res.result;
        this.formList = result.records;
        this.formTotal = result.total;
        this.formDeploy.open = true;
        this.formDeploy.title = "挂载表单";
      })
    },
    /** 挂载表单 */
    submitFormDeploy(row){
      this.formDeployParam.formId = row.formId;
      addDeployForm(this.formDeployParam).then(res =>{
        this.$modal.msgSuccess(res.message);
        this.formDeploy.open = false;
        this.formQueryParams.formName = null;
        this.getList();
      })
    },
    handleCurrentChange(data) {
      if (data) {
        this.currentRow = JSON.parse(data.formContent);
      }
    },

    /** 获取数据类型 */
    dataType(data){
      this.users = [];
      this.groups = [];
      if (data) {
        if (data.dataType === 'dynamic') {
          if (data.userType === 'assignee') {
            this.users = [{id: "${INITIATOR}", name: "${INITIATOR}"},
              {id: "#{approval}", name: "#{approval}"}
            ]
          } else if (data.userType === 'candidateUsers') {
            this.users = [ {id: "#{approval}", name: "#{approval}"}]
          } else {
            this.groups = [{id: "#{approval}", name: "#{approval}"}]
          }
        } else {
          this.initUserAndRole()
        }
      }
    },
    handleClose(){
      this.xmlFrame.open = false
    },
    /** 展示xml */
    showXML(data){
      this.xmlTitle = 'xml查看';
      this.xmlOpen = true;
      this.xmlContent = vkbeautify.xml(data);
    },
  },
  computed: {
    getContainer() {
      return document.querySelector('#app')
    }
  }
};
</script>
<style lang="scss">
  .flow-containers .canvas{
    margin: 0px;
    .djs-container{
      > svg{
        border: solid 1px var(--palette-border-color);
        border-top: none;
      }
    }
  }
  .canvas .bjs-powered-by {
    display: none;
  }
  .canvas {
    margin: 10px;
  }
  >>> .nodeSuccess:not(.djs-connection) {
    .djs-visual {
      > :nth-child(1) {
        stroke: #f70e0e !important;
        stroke-width: 3px !important;
      }
    }
  }
</style>